package com.baijia.commons.util;

import com.baijia.commons.tianxiao.OrgAppToken;

import com.google.common.base.Splitter;
import com.google.common.io.BaseEncoding;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public final class EncryptUtils {
    
    private static final Charset charset = Charset.forName("CP437");

    private static byte[] DEF_KEY = "NP1=~0710*(kZV)M".getBytes();

    private static String DEF_CHARSET = "UTF-8";
    
    private static int SALT_LENGTH = 8;
    
    public static String encodeWithAES(String data) throws Exception {
        if (StringUtils.isBlank(data)) {
            return "";
        }
        byte[] dataBytes = data.getBytes(DEF_CHARSET);
        SecretKeySpec skey = new SecretKeySpec(DEF_KEY, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        byte[] result = cipher.doFinal(dataBytes);
        return Base64.encodeBase64String(result);
    }

    public static String decodeWithAES(String data) throws Exception {
        byte[] dataBytes = Base64.decodeBase64(data);
        SecretKeySpec skey = new SecretKeySpec(DEF_KEY, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skey);
        byte[] result = cipher.doFinal(dataBytes);
        return new String(result, DEF_CHARSET);
    }

    /**
     * 解析app登录token
     * @param token
     * @return
     */
    public static String strDecode(String token) {
        String src = base64Decode(token);
        int factor = src.charAt(0);
        int c = factor % 8;
        String entity = src.substring(1);
        List<String> slice = Splitter.fixedLength(factor).splitToList(entity);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < slice.size(); i++) {
            byte[] chars = slice.get(i).getBytes(charset);
            for (int j = 0; j < chars.length; j++) {
                byte ch = chars[j];
                int t = ch - c - i;
                if (t < 0) {
                    t += 256;
                }
                sb.append((char) t);
            }
        }
        return sb.toString();
    }

    public static String base64Decode(String src) {
        if (StringUtils.isBlank(src)) {
            return "";
        } else {
            String deStr = src.replace('-', '+').replace('_', '/');
            return new String(BaseEncoding.base64().decode(deStr), charset);
        }
    }
    
    /**
     * APP登录生成token
     * 
     * @param userId
     * @return token
     */
    public static String strEncode(Integer userId) throws Exception{
        // 步骤一：生成三个属性的json，时间精确到秒
        String salt = PasswordUtil.randomStr(SALT_LENGTH);
        OrgAppToken appAuthToken = new OrgAppToken();
        appAuthToken.setCt((int) (System.currentTimeMillis()/1000));
        appAuthToken.setSalt(salt);
        appAuthToken.setUser_id(userId);
        String str = JacksonUtil.obj2Str(appAuthToken);
        // 步骤二：生成加密因子 rand(1,min(255, Math.ceil(len%3));
        Random random = new Random();
        int factor = random.nextInt((int) Math.min(255.0, Math.ceil(str.length()/3.0)))+1;
        int c = factor % 8;
        // 步骤三：字符换值
        List<String> slice = Splitter.fixedLength(factor).splitToList(str);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < slice.size(); i++) {
            byte[] chars = slice.get(i).getBytes(charset);
            for (int j = 0; j < chars.length; j++) {
                byte ch = chars[j];
                byte t = (byte) (ch + c + i);
                sb.append(new String(new byte[]{t},charset));
            }
        }
        String token = base64Encode(factor, sb.toString());
        return token;
    }
    /**
     * APP子帐号登录生成token
     * 
     * @param userId
     * @return token
     */
    public static String strEncode(Integer userId,Long cascade_user_id, String auth, Integer ts) throws Exception{
        // 步骤一：生成三个属性的json，时间精确到秒
        String salt = PasswordUtil.randomStr(SALT_LENGTH);
        OrgAppToken appAuthToken = new OrgAppToken();
        appAuthToken.setCt(ts);
        appAuthToken.setSalt(salt);
        appAuthToken.setUser_id(userId);
        appAuthToken.setCascade_user_id(cascade_user_id);
        appAuthToken.setAuth(auth);
        String str = JacksonUtil.obj2Str(appAuthToken);
        // 步骤二：生成加密因子 rand(1,min(255, Math.ceil(len%3));
        Random random = new Random();
        int factor = random.nextInt((int) Math.min(255.0, Math.ceil(str.length()/3.0)))+1;
        int c = factor % 8;
        // 步骤三：字符换值
        List<String> slice = Splitter.fixedLength(factor).splitToList(str);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < slice.size(); i++) {
            byte[] chars = slice.get(i).getBytes(charset);
            for (int j = 0; j < chars.length; j++) {
                byte ch = chars[j];
                byte t = (byte) (ch + c + i);
                sb.append(new String(new byte[]{t},charset));
            }
        }
        String token = base64Encode(factor, sb.toString());
        return token;
    }
    
    public static String base64Encode(int factor, String src) {
        if (StringUtils.isBlank(src)) {
            return "";
        } else {
            src = ((char)factor)+src;
            String deStr = BaseEncoding.base64().encode(src.getBytes(charset));
            String result = deStr.replace('+', '-').replace('/', '_');
            while(result.endsWith("=")){
                result = result.substring(0, result.length()-1).toString();
            }
            return result;
        }
    }
}
